<?php
class Wlib_Doctrine_Task_SafeMigrateTask extends Doctrine_Task
{
    public $description =   'Safe migrate database to latest version or the specified version';
    public $requiredArguments = array('migrations_path' => 'Specify path to your migrations directory.',
                                      'migration_table_name' => 'Specify table name');
    public $optionalArguments = array(
        'version' => 'Version to migrate to. If you do not specify, the db will be migrated from the current version to the latest. For show current version - specify "?"',
        'up' => 'Migrate up one version',
        'down' => 'Migrate down one version',
        'dry-run' => 'Do not persist migrations',
    );
    public $taskName = 'safe-migrate-task';

    public function execute()
    {
        $options = array();

        $arguments = $this->getArguments();

        foreach(array('up', 'down', 'dry-run') as $argKey) {
            if(in_array($argKey, $arguments)) {
                $options[$argKey] = true;
            } else {
                $options[$argKey] = false;
            }
        }

        $argVersion = $this->getArgument('version');

        $migration = new Doctrine_Migration($this->getArgument('migrations_path'));
        $migration->setTableName($this->getArgument('migration_table_name'));
        $from = $migration->getCurrentVersion();

        if($argVersion === '?') {
            $nextVersion = sprintf("%05d", ($from+1));
            $this->notify(sprintf('Current version: %s. Name for next migration file %s_*.php', $from, $nextVersion));
            return 0;
        }

        if (is_numeric($argVersion)) {
            $version = $argVersion;
        } else if ($options['up']) {
            $version = $from + 1;
        } else if ($options['down']) {
            $version = $from - 1;
        } else {
            $version = $migration->getLatestVersion();
        }

        if ($from == $version) {
            $this->notify(sprintf('Already at migration version %s', $version));
            return;
        }

        $this->notify(sprintf('Migrating from version %s to %s%s', $from, $version, $options['dry-run'] ? ' (dry run)' : ''));
        try {
            $migration->migrate($version, $options['dry-run']);
        } catch (Exception $e) {
            if(!$migration->hasErrors()) {
                throw $e;
            }
        }

        if ($migration->hasErrors()) {        
            $this->notify('The following errors occurred:');
            foreach ($migration->getErrors() as $error)
            {
                $this->notify($error);
            }
            return 1;
        }

        $this->notify('Migration complete');
    }
}